﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading;
using yq.IBase.Basis;

namespace yq.IBase.Cache
{
    /// <summary>
    /// List 缓存
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class IListCaChe<T> where T : class ,new()
    {

        static bool isBind = true;

        public IListCaChe()
        {
            if (isBind)
            {
                isBind = false;
                CacheManage.Bind(LinkClass(), Cache());
            }
        }

        /// <summary>
        /// 内部共享锁
        /// </summary>
        private static readonly ReaderWriterLock _rwlock = new ReaderWriterLock();
        private int readOutTime = 1000;

        /// <summary>
        /// 关联的Class 
        /// </summary>
        protected abstract IList<Type> LinkClass();


        /// <summary>
        /// 加载数据 
        /// </summary>
        protected abstract IList<T> LocdAll();

        /// <summary>
        /// 缓存处理方式
        /// </summary>
        /// <returns></returns>
        protected virtual DefaultCache Cache()
        {
            return new DefaultCache();
        }

        /// <summary>
        /// 是否加载了缓存
        /// </summary>
        /// <returns></returns>
        private bool ContainsKey()
        {
            return Cache().ContainsKey<T>();
        }

        /// <summary>
        /// 如果没有加载数据先加载数据
        /// 然后执行委托
        /// </summary>
        /// <typeparam name="R"></typeparam>
        /// <param name="func"></param>
        /// <returns></returns>
        private R Task<R>(Func<R> func)
        {
            IList<T> list = new List<T>();
            _rwlock.AcquireReaderLock(readOutTime);
            try
            {
                if (ContainsKey() == false)
                {
                    // 提升读锁到写锁 
                    LockCookie lc = _rwlock.UpgradeToWriterLock(readOutTime);
                    try
                    {
                        list = LocdAll();
                        Cache().Write<T>(list);
                    }
                    finally
                    {
                        // 下降写锁 
                        _rwlock.DowngradeFromWriterLock(ref lc);
                    }
                }

                //运行
                return func();
            }
            finally
            {
                // 释放原来的读锁 
                _rwlock.ReleaseReaderLock();
            }
        }

        /// <summary>
        /// 返回所有数据
        /// </summary>
        /// <returns></returns>
        public IList<T> GetListAll()
        {
            Func<IList<T>> func = () =>
            {
                return Cache().Read<T>();
            };

            return Task(func);
        }

        /// <summary>
        /// 返回所有数据
        /// </summary>
        /// <returns></returns>
        public void Delete()
        {
            string fullName = new T().GetType().FullName;
            Cache().Delete(fullName);
        }
    }

}
